package com.zyf.project.kvdb.protocol.proto.impl;

import com.zyf.project.binaryproto.type.PrimitiveType;
import com.zyf.project.kvdb.protocol.proto.Message;
import com.zyf.project.kvdb.protocol.proto.MessageContent;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import utils.binary.impl.Bytes;

import java.util.concurrent.atomic.AtomicLong;

import static com.zyf.project.kvdb.protocol.proto.Command.CommandType.*;

/**
 * <h1>KVDB 封装消息</h1>
 * <p>实现了 {@link Message} 接口</p>
 *
 * @author Zhou Yifan
 */
public class KVDBMessage implements Message {

    private static AtomicLong idIndexer = new AtomicLong(0);

    private Long id;

    private MessageContent content;

    public KVDBMessage(MessageContent content) {
        this(idIndexer.getAndIncrement(), content);
    }

    public KVDBMessage(Long id, MessageContent content) {
        this.id = id;
        this.content = content;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public void setContent(MessageContent content) {
        this.content = content;
    }

    /**
     * 获取消息 ID
     *
     * @return Long 值，键值对操作类型为 {@link PrimitiveType#INT64}
     */
    @Override
    public Long getId() {
        return id;
    }

    /**
     * 消息体，设置为可嵌套的键值数据类型
     *
     * @return {@link MessageContent}
     */
    @Override
    public MessageContent getContent() {
        return content;
    }

    /* Message for request */

    /**
     * 切换数据库的消息
     *
     * @param key 数据库名
     * @return {@link Message}
     */
    @Contract("_ -> new")
    public static @NotNull Message use(String key) {
        return new KVDBMessage(new KVDBCommand(USE.getCommand(), Bytes.fromString(key)));
    }

    /**
     * 创建数据库的消息
     *
     * @param parameter 数据库信息，{@link Bytes} 类型
     * @return {@link Message}
     */
    @Contract("_ -> new")
    public static @NotNull Message createDatabase(Bytes parameter) {
        return new KVDBMessage(new KVDBCommand(CREATE_DATABASE.getCommand(), parameter));
    }

    /**
     * 开启数据库的消息
     *
     * @param database 数据库名
     * @return {@link Message}
     */
    @Contract("_ -> new")
    public static @NotNull Message enableDatabase(String database) {
        return new KVDBMessage(new KVDBCommand(ENABLE_DATABASE.getCommand(), Bytes.fromString(database)));
    }

    /**
     * 关闭数据库的消息
     *
     * @param database 数据库名
     * @return {@link Message}
     */
    @Contract("_ -> new")
    public static @NotNull Message disableDatabase(String database) {
        return new KVDBMessage(new KVDBCommand(DISABLE_DATABASE.getCommand(), Bytes.fromString(database)));
    }

    /**
     * 删除数据库的消息
     *
     * @param database 数据库名
     * @return {@link Message}
     */
    @Contract("_ -> new")
    public static @NotNull Message dropDatabase(String database) {
        return new KVDBMessage(new KVDBCommand(DROP_DATABASE.getCommand(), Bytes.fromString(database)));
    }

    /**
     * 服务器集群配置消息
     *
     * @return {@link Message}
     */
    @Contract(" -> new")
    public static @NotNull Message clusterInfo() {
        return new KVDBMessage(new KVDBCommand(CLUSTER_INFO.getCommand()));
    }

    /**
     * 展示所有数据库实例信息消息
     *
     * @return {@link Message}
     */
    @Contract(" -> new")
    public static @NotNull Message showDatabases() {
        return new KVDBMessage(new KVDBCommand(SHOW_DATABASES.getCommand()));
    }

    /**
     * 存在型判断的消息
     *
     * @param keys 待判断的键
     * @return {@link Message}
     */
    @Contract("_ -> new")
    public static @NotNull Message exists(Bytes... keys) {
        return new KVDBMessage(new KVDBCommand(EXISTS.getCommand(), keys));
    }

    /**
     * 添加键的消息
     *
     * @param keys 待添加的键
     * @return {@link Message}
     */
    @Contract("_ -> new")
    public static @NotNull Message put(Bytes... keys) {
        return new KVDBMessage(new KVDBCommand(PUT.getCommand(), keys));
    }

    /**
     * 获取键的值的消息
     *
     * @param keys 待查找的键
     * @return {@link Message}
     */
    @Contract("_ -> new")
    public static @NotNull Message get(Bytes... keys) {
        return new KVDBMessage(new KVDBCommand(GET.getCommand(), keys));
    }

    /**
     * 开启批处理的消息
     *
     * @param kvs 键值对数组
     * @return {@link Message}
     */
    @Contract("_ -> new")
    public static @NotNull Message batchBegin(Bytes... kvs) {
        return new KVDBMessage(new KVDBCommand(BATCH_BEGIN.getCommand(), kvs));
    }

    /**
     * 取消批处理的消息
     *
     * @param kvs 键值对数组
     * @return {@link Message}
     */
    @Contract("_ -> new")
    public static @NotNull Message batchAbort(Bytes... kvs) {
        return new KVDBMessage(new KVDBCommand(BATCH_ABORT.getCommand(), kvs));
    }

    /**
     * 提交批处理的消息
     *
     * @param kvs 键值对数组
     * @return {@link Message}
     */
    @Contract("_ -> new")
    public static @NotNull Message batchCommit(Bytes... kvs) {
        return new KVDBMessage(new KVDBCommand(BATCH_COMMIT.getCommand(), kvs));
    }

}
